#pragma once
#include <nlohmann/json.hpp>
#include <string>
#include <vector>

#include "action.hpp"
#include "event.hpp"
#include "factory.hpp"

class Rule
{
  public:
    std::shared_ptr<Event> event;
    std::vector<std::shared_ptr<Action>> actions;

  private:
    std::vector<std::shared_future<bool>> futures;
    bool isRuning = false;

  public:
    Rule(const nlohmann::json &j)
    {
        event = Factory<Event>::Instance().Create(j["event"]);
        for (auto &action : j["actions"])
        {
            actions.emplace_back(Factory<Action>::Instance().Create(action));
        }
        futures.resize(actions.size());
    }
    bool IsRunning() const { return isRuning; }
    void AsyncExecute()
    {
        isRuning = true;
        for (int i = 0; i < actions.size(); i++)
        {
            futures[i] = actions[i]->AsyncExecute();
        }
    }
    void AsyncTerminate()
    {
        for (auto &action : actions)
        {
            action->AsyncTerminate();
        }
        isRuning = false;
    }
    bool CheckFinished()
    {
        for (int i = 0; i < futures.size(); i++)
        {
            if (futures[i].valid())
            {
                std::future_status status = futures[i].wait_for(std::chrono::milliseconds(0));
                if (status != std::future_status::ready)
                {
                    return false;
                }
            }
        }
        isRuning = false;
        return true;
    }
};